package com.mlethe.library.socialtool.core;

import android.content.Context;
import android.content.Intent;

import com.mlethe.library.socialtool.callback.Callback;
import com.mlethe.library.socialtool.callback.OauthActionListener;
import com.mlethe.library.socialtool.callback.PayActionListener;
import com.mlethe.library.socialtool.callback.ShareActionListener;
import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.modelpay.PayResp;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

import org.json.JSONObject;

/**
 * 微信登录、支付
 *
 * @author Mlethe
 * @date 2018/1/11
 */
public class Wechat implements Oauth<IWXAPI> {

    private static final String BASE_URL = "https://api.weixin.qq.com/sns/";

    private Context mContext;
    private final String mAppid;
    private final String mSecret;

    private IWXAPI mApi;
    private EventHandler mEventHandler;

    private OauthActionListener mOauthListener;
    private PayActionListener mPayListener;

    /**
     * 是否获取用户信息
     */
    private boolean isGetUserInfo = false;

    /**
     * @param context
     * @param appid   微信 AppId
     * @param secret  微信 secret(不需要本地获取用户信息时不需要secret)
     */
    public Wechat(Context context, String appid, String secret) {
        this.mContext = context;
        this.mAppid = appid;
        this.mSecret = secret;
        mEventHandler = new EventHandler();
    }

    @Override
    public IWXAPI getApi() {
        if (mApi == null) {
            this.mApi = WXAPIFactory.createWXAPI(mContext.getApplicationContext(), mAppid, false);
            // 将该app注册到微信
            mApi.registerApp(mAppid);
        }
        return mApi;
    }

    /**
     * 授权登录回调
     * 请在调用 oauth() 方法前调用
     *
     * @param listener listener
     * @return
     */
    public Wechat setOauthActionListener(OauthActionListener listener) {
        this.mOauthListener = listener;
        return this;
    }

    public OauthActionListener getOauthActionListener() {
        return mOauthListener;
    }

    /**
     * 支付回调
     * 请在调用 pay() 方法前调用
     *
     * @param listener listener
     * @return
     */
    public Wechat setPayActionListener(PayActionListener listener) {
        this.mPayListener = listener;
        return this;
    }

    /**
     * 授权、分享、支付结果处理
     *
     * @return
     */
    public boolean handleIntent(Intent intent) {
        try {
            return getApi().handleIntent(intent, mEventHandler);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 是否获取用户信息
     * @param flag true 是 false 否
     */
    public Wechat setGetInfoEnable(boolean flag) {
        isGetUserInfo = flag;
        return this;
    }

    /**
     * 登录微信授权，取用户个人信息 授权作用域为snsapi_userinfo，状态为wechat_sdk_login
     */
    public void oauth() {
        oauth("wechat_sdk_login");
    }

    /**
     * 登录微信授权，取用户个人信息 授权作用域为snsapi_userinfo
     *
     * @param state
     */
    public void oauth(String state) {
        oauth("snsapi_userinfo", state);
    }

    /**
     * 登录微信授权
     *
     * @param scope 应用授权作用域，如获取用户个人信息则填写snsapi_userinfo
     * @param state 微信用于保持请求和回调的状态，授权请求后原样带回给第三方。该参数可用于防止csrf攻击（跨站请求伪造攻击）
     */
    public void oauth(String scope, String state) {
        if (!isAppInstalled()) {
            if (mOauthListener != null) {
                mOauthListener.onNotInstalled(Platform.WECHAT);
                mOauthListener = null;
            }
            return;
        }
        SendAuth.Req req = new SendAuth.Req();
        req.scope = scope;
        req.state = Util.buildTransaction(state);
        getApi().sendReq(req);
    }

    /**
     * 获取Code
     *
     * @param baseResp
     * @return
     */
    public String getCode(SendAuth.Resp baseResp) {
        return baseResp.code;
    }

    /**
     * 获取用户信息
     *
     * @param baseResp
     */
    public void getUserInfo(SendAuth.Resp baseResp) {
        String code = getCode(baseResp);
        if (code != null) {
            getToken(code);
        } else {
            mOauthListener = null;
        }
    }

    /**
     * 获取token
     *
     * @param code
     */
    private void getToken(String code) {
        new HttpsThread(BASE_URL + "oauth2/access_token?appid=" + mAppid + "&secret=" + mSecret + "&code=" + code + "&grant_type=authorization_code", new Callback() {
            @Override
            public void onSuccess(JSONObject jsonObject) throws Exception {
                if (!jsonObject.has("errcode")) {
                    String token = jsonObject.getString("access_token");
                    String openid = jsonObject.getString("openid");
                    getInfo(token, openid);
                } else {
                    int errcode = jsonObject.getInt("errcode");
                    String errmsg = jsonObject.getString("errmsg");
                    if (mOauthListener != null) {
                        mOauthListener.onFail(Platform.WECHAT);
                        mOauthListener = null;
                    }
                }
            }

            @Override
            public void onError(Exception e) {
                if (mOauthListener != null) {
                    mOauthListener.onFail(Platform.WECHAT);
                    mOauthListener = null;
                }
            }
        }).start();
    }

    /**
     * 真实获取用户信息
     *
     * @param token
     * @param openid
     */
    private void getInfo(String token, String openid) {
        new HttpsThread(BASE_URL + "userinfo?access_token=" + token + "&openid=" + openid, new Callback() {
            @Override
            public void onSuccess(JSONObject jsonObject) throws Exception {
                if (mOauthListener != null) {
                    mOauthListener.onComplete(Platform.WECHAT, jsonObject);
                    mOauthListener = null;
                }
            }

            @Override
            public void onError(Exception e) {
                if (mOauthListener != null) {
                    mOauthListener.onFail(Platform.WECHAT);
                    mOauthListener = null;
                }
            }
        }).start();
    }

    /**
     * 调起微信支付
     *
     * @param wxPay
     * @param extData optional  其他参数
     */
    /**
     * 调起微信支付
     *
     * @param appId        微信appId
     * @param partnerId    商户号
     * @param prepayId     预支付交易会话ID
     * @param nonceStr     随机字符串
     * @param timeStamp    时间戳
     * @param packageValue 扩展字段，暂填写固定值Sign=WXPay
     * @param sign         签名
     * @param extData      optional  其他参数
     */
    public void pay(String appId, String partnerId, String prepayId, String nonceStr, long timeStamp, String packageValue, String sign, String extData) {
        if (!isAppInstalled()) {
            if (mPayListener != null) {
                mPayListener.onNotInstalled(Platform.WECHAT);
                mPayListener = null;
            }
            return;
        }
        PayReq req = new PayReq();
        req.appId = appId;
        req.partnerId = partnerId;
        req.prepayId = prepayId;
        req.nonceStr = nonceStr;
        req.timeStamp = String.valueOf(timeStamp);
        req.packageValue = packageValue;
        req.sign = sign;
        req.extData = extData;
        /**
         * 在支付之前，如果应用没有注册到微信，应该先调用IWXMsg.registerApp将应用注册到微信
         */
        getApi().sendReq(req);
    }

    /**
     * 判断是否安装
     *
     * @return
     */
    @Override
    public boolean isAppInstalled() {
        if (getApi() == null || !getApi().isWXAppInstalled()) {
            return false;
        }
        return true;
    }

    /**
     * 取消注册
     */
    @Override
    public void unregister() {
        if (mApi != null) {
            mApi.unregisterApp();
            mApi = null;
        }
    }

    /**
     * 释放内存
     */
    @Override
    public void release() {
        unregister();
        mContext = null;
        mEventHandler = null;
        mOauthListener = null;
        mPayListener = null;
    }

    /**
     * 回调处理类
     */
    private class EventHandler implements IWXAPIEventHandler {

        @Override
        public void onReq(BaseReq baseReq) {
            switch (baseReq.getType()) {
                case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:
                    break;
                case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:
                    break;
                default:
                    break;
            }
        }

        @Override
        public void onResp(BaseResp baseResp) {
            handleResult(baseResp);
        }
    }

    /**
     * 处理返回结果
     */
    public void handleResult(BaseResp baseResp) {
        int type = baseResp.getType();
        try {
            int errCode = baseResp.errCode;
            if (type == ConstantsAPI.COMMAND_SENDAUTH) {
                // 授权登录
                if (mOauthListener == null) {
                    return;
                }
                if (errCode == BaseResp.ErrCode.ERR_OK) {
                    // 授权成功
                    SendAuth.Resp sendResp = (SendAuth.Resp) baseResp;
                    if (isGetUserInfo) {
                        isGetUserInfo = false;
                        getUserInfo(sendResp);
                    } else {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("code", getCode(sendResp));
                        mOauthListener.onComplete(Platform.WECHAT, jsonObject);
                        mOauthListener = null;
                    }
                } else if (errCode == BaseResp.ErrCode.ERR_USER_CANCEL) {
                    // 授权取消
                    mOauthListener.onCancel(Platform.WECHAT);
                    mOauthListener = null;
                } else if (errCode == BaseResp.ErrCode.ERR_AUTH_DENIED) {
                    // 权限验证失败
                    mOauthListener.onFail(Platform.WECHAT);
                    mOauthListener = null;
                } else if (errCode == BaseResp.ErrCode.ERR_SENT_FAILED) {
                    // 授权失败
                    mOauthListener.onFail(Platform.WECHAT);
                    mOauthListener = null;
                } else {
                    // 未知错误
                    mOauthListener.onFail(Platform.WECHAT);
                    mOauthListener = null;
                }
            } else if (type == ConstantsAPI.COMMAND_SENDMESSAGE_TO_WX) {
                // 分享
                ShareActionListener listener = WechatShare.getShareActionListener();
                if (listener == null) {
                    return;
                }
                if (errCode == BaseResp.ErrCode.ERR_OK) {
                    // 发送成功
                    listener.onComplete(Platform.WECHAT);
                } else if (errCode == BaseResp.ErrCode.ERR_USER_CANCEL) {
                    // 发送取消
                    listener.onCancel(Platform.WECHAT);
                } else if (errCode == BaseResp.ErrCode.ERR_AUTH_DENIED) {
                    // 权限验证失败
                    listener.onFail(Platform.WECHAT);
                } else if (errCode == BaseResp.ErrCode.ERR_SENT_FAILED) {
                    // 发送失败
                    listener.onFail(Platform.WECHAT);
                } else {
                    // 未知错误
                    listener.onFail(Platform.WECHAT);
                }
                WechatShare.setShareActionListener(null);
            } else if (type == ConstantsAPI.COMMAND_PAY_BY_WX) {
                // 支付
                if (mPayListener == null) {
                    return;
                }
                if (errCode == BaseResp.ErrCode.ERR_OK) {
                    // 支付成功
                    PayResp payResp = (PayResp) baseResp;
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("extData", payResp.extData);
                    jsonObject.put("openId", payResp.openId);
                    jsonObject.put("returnKey", payResp.returnKey);
                    jsonObject.put("prepayId", payResp.prepayId);
                    mPayListener.onComplete(Platform.WECHAT, jsonObject);
                } else if (errCode == BaseResp.ErrCode.ERR_USER_CANCEL) {
                    // 支付取消
                    mPayListener.onCancel(Platform.WECHAT);
                } else if (errCode == BaseResp.ErrCode.ERR_AUTH_DENIED) {
                    // 权限验证失败
                    mPayListener.onFail(Platform.WECHAT);
                } else if (errCode == BaseResp.ErrCode.ERR_SENT_FAILED) {
                    // 授权失败
                    mPayListener.onFail(Platform.WECHAT);
                } else {
                    // 未知错误
                    mPayListener.onFail(Platform.WECHAT);
                }
                mPayListener = null;
            }
        } catch (Exception e) {
            if (type == ConstantsAPI.COMMAND_SENDAUTH) {
                mOauthListener = null;
            } else if (type == ConstantsAPI.COMMAND_SENDMESSAGE_TO_WX) {
                WechatShare.setShareActionListener(null);
            } else if (type == ConstantsAPI.COMMAND_PAY_BY_WX) {
                mPayListener = null;
            }
            e.printStackTrace();
        }
    }
}
